﻿#include "task.h"
#include "base/basetype.h"
#include <QTimer>

namespace yc {

Task::Task(int timeout, QObject* parent) : Task(0, true, timeout, parent) { }

Task::Task(int id, bool auto_delete, int timeout, QObject* parent)
    : QObject(parent),
      id_(id),
      auto_delete_(auto_delete),
      priority_(0),
      status_(NOT_START_STATUS),
      timer_(nullptr)
{
    connect(this, &Task::finished, this, [this] {
        if (isRunning()) {
            stopTimeoutTimer();
            end_time_ = QDateTime::currentDateTime();
            status_ = FINISHED_STATUS;
            if (auto_delete_) {
                deleteLater();
            }
        }
    });
    connect(this, &Task::failed, this, [this](int error, const QString& message) {
        Q_UNUSED(error)
        Q_UNUSED(message)
        if (isRunning()) {
            stopTimeoutTimer();
            end_time_ = QDateTime::currentDateTime();
            status_ = FAILED_STATUS;
            if (auto_delete_) {
                deleteLater();
            }
        }
    });
    if (timeout > 0) {
        startTimeoutTimer(timeout);
    }
}

int Task::timeout() const
{
    return (timer_ ? timer_->interval() : -1);
}

QString Task::statusMessage() const
{
    return QString();
}

qint64 Task::elapsedMSecs() const
{
    if (isRunning()) {
        return start_time_.msecsTo(QDateTime::currentDateTime());
    }
    return (status_ == NOT_START_STATUS ? 0 : start_time_.msecsTo(end_time_));
}

qint64 Task::evaluateTotalMSecs() const
{
    return 0;
}

void Task::startTimeoutTimer(int timeout)
{
    stopTimeoutTimer();
    if (timeout > 0) {
        if (!timer_) {
            timer_ = new QTimer(this);
            timer_->setInterval(timeout);
            timer_->setSingleShot(true);
            connect(timer_, &QTimer::timeout, this, [this] {
                timer_->stop();
                if (isRunning()) {
                    onTimeout();
                    if (isRunning()) {
                        Q_EMIT failed(TIMEOUT_ERROR, tr("Timeout"));
                    }
                }
            });
        }
        timer_->start(timeout);
    }
}

void Task::stopTimeoutTimer()
{
    if (timer_) {
        timer_->stop();
    }
}

void Task::start()
{
    if (!isRunning()) {
        Q_EMIT aboutToStart();
        status_ = RUNNING_STATUS;
        start_time_ = QDateTime::currentDateTime();
        if (timer_) {
            timer_->start();
        }
        startImpl();
    }
}

void Task::terminate()
{
    if (isRunning()) {
        terminateImpl();
        Q_EMIT failed(CANCEL_ERROR, tr("Cancelled."));
    }
}
} // namespace yc
